package com.lfc.myframe.utils

import android.os.Parcelable
import android.text.TextUtils
import android.util.Base64
import com.lfc.myframe.share.MMKVHub
import com.tencent.mmkv.MMKV
import java.io.*
import java.util.*

object MMKVUtil {
    var mmkv: MMKV? = null

    init {
        mmkv = MMKV.defaultMMKV()
    }

    fun encode(key: String, value: Any?) {
        when (value) {
            is String -> mmkv?.encode(key, value)
            is Float -> mmkv?.encode(key, value)
            is Boolean -> mmkv?.encode(key, value)
            is Int -> mmkv?.encode(key, value)
            is Long -> mmkv?.encode(key, value)
            is Double -> mmkv?.encode(key, value)
            is ByteArray -> mmkv?.encode(key, value)
            is Nothing -> return
        }
    }

    fun <T : Parcelable> encode(key: String, t: T?) {
        if (t == null) {
            return
        }
        mmkv?.encode(key, t)
    }

    fun encode(key: String, sets: Set<String>?) {
        if (sets == null) {
            return
        }
        mmkv?.encode(key, sets)
    }

    fun decodeInt(key: String): Int? {
        return mmkv?.decodeInt(key, 0)
    }

    fun decodeDouble(key: String): Double? {
        return mmkv?.decodeDouble(key, 0.00)
    }

    fun decodeLong(key: String): Long? {
        return mmkv?.decodeLong(key, 0L)
    }

    fun decodeBoolean(key: String, isValue: Boolean = false): Boolean? {
        return mmkv?.decodeBool(key, isValue)
    }

    fun decodeFloat(key: String): Float? {
        return mmkv?.decodeFloat(key, 0F)
    }

    fun decodeByteArray(key: String): ByteArray? {
        return mmkv?.decodeBytes(key)
    }

    fun decodeString(key: String): String? {
        return mmkv?.decodeString(key, "")
    }

    fun <T : Parcelable> decodeParcelable(key: String, tClass: Class<T>): T? {
        return mmkv?.decodeParcelable(key, tClass)
    }

    fun decodeStringSet(key: String): Set<String>? {
        return mmkv?.decodeStringSet(key, Collections.emptySet())
    }

    fun removeKey(key: String) {
        mmkv?.removeValueForKey(key)
    }

    fun clearAll() {
        mmkv?.clearAll()
    }

    fun clearLoginInfo() {
        mmkv?.removeValueForKey(MMKVHub.KEY_USERTOKEN)
        mmkv?.removeValueForKey(MMKVHub.KEY_USERINFO)
        mmkv?.removeValueForKey(MMKVHub.KEY_ISCompanyCombo)
        mmkv?.removeValueForKey(MMKVHub.KEY_IMUserName)
        mmkv?.removeValueForKey(MMKVHub.KEY_IMUserToken)
        mmkv?.removeValueForKey(MMKVHub.KEY_SELFLAWYERUserNAME)
        mmkv?.removeValueForKey(MMKVHub.KEY_SELFLAWYERUserNickName)
        mmkv?.removeValueForKey(MMKVHub.KEY_SELFLAWYERIMUserID)
    }

    /*
       ************************************  实体类保存操作  **************************************************************************
        */
    fun encodeObject(key: String, any: Any) {
        //先将序列化结果写到byte缓存中，其实就分配一个内存空间
        //先将序列化结果写到byte缓存中，其实就分配一个内存空间
        val bos = ByteArrayOutputStream()
        var os: ObjectOutputStream? = null
        try {
            os = ObjectOutputStream(bos)
            os.writeObject(any) //将对象序列化写入byte缓存
        } catch (e: IOException) {
            e.printStackTrace()
        }
        //将序列化的数据转为16进制保存
        //将序列化的数据转为16进制保存
        val bytesToHexString: String =
            bytesToHexString(bos.toByteArray()).toString()
        encode(key, bytesToHexString)
    }

    fun decodeObject(stringKey: String): Any? {
        var strSample = decodeString(stringKey).toString()
        if (strSample == null || TextUtils.isEmpty(strSample))
            return null
        else {
            //将16进制的数据转为数组，准备反序列化
            val stringToBytes: ByteArray =
                StringToBytes(strSample)!!
            val bis = ByteArrayInputStream(stringToBytes)
            var `is`: ObjectInputStream? = null
            //返回反序列化得到的对象
            //返回反序列化得到的对象
            var readObject: Any? = null
            try {
                `is` = ObjectInputStream(bis)
                readObject = `is`.readObject()
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
            return readObject

        }
        return null

    }

    /**
     * desc:将16进制的数据转为数组
     *
     * @param data
     * @return
     */
    fun StringToBytes(data: String): ByteArray? {
        val hexString = data.toUpperCase().trim { it <= ' ' }
        if (hexString.length % 2 != 0) {
            return null
        }
        val retData = ByteArray(hexString.length / 2)
        var i = 0
        while (i < hexString.length) {
            var int_ch: Int // 两位16进制数转化后的10进制数
            val hex_char1 = hexString[i] //两位16进制数中的第一位(高位*16)
            var int_ch1: Int
            int_ch1 =
                if (hex_char1 >= '0' && hex_char1 <= '9') (hex_char1.toInt() - 48) * 16 // 0 的Ascll - 48
                else if (hex_char1 >= 'A' && hex_char1 <= 'F') (hex_char1.toInt() - 55) * 16 // A 的Ascll - 65
                else return null
            i++
            val hex_char2 = hexString[i] //两位16进制数中的第二位(低位)
            var int_ch2: Int
            int_ch2 =
                if (hex_char2 >= '0' && hex_char2 <= '9') hex_char2.toInt() - 48 // 0 的Ascll - 48
                else if (hex_char2 >= 'A' && hex_char2 <= 'F') hex_char2.toInt() - 55 // A 的Ascll - 65
                else return null
            int_ch = int_ch1 + int_ch2
            retData[i / 2] = int_ch.toByte() //将转化后的数放入Byte里
            i++
        }
        return retData
    }

    /**
     * desc:将数组转为16进制
     *
     * @param bArray
     * @return
     */
    fun bytesToHexString(bArray: ByteArray?): String? {
        if (bArray == null) {
            return null
        }
        if (bArray.size == 0) {
            return ""
        }
        val sb = StringBuffer(bArray.size)
        var sTemp: String
        for (i in bArray.indices) {
            sTemp = Integer.toHexString(0xFF and bArray[i].toInt())
            if (sTemp.length < 2) sb.append(0)
            sb.append(sTemp.toUpperCase())
        }
        return sb.toString()
    }

    /*
    ************************************  List保存操作  **************************************************************************
     */
    fun encodeList(key: String, mutableList: List<Any>): Boolean {
        var str_value = ""
        try {
            str_value = SceneList2String(mutableList)
            encode(key, str_value)
            return true
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    fun decodeList(key: String): MutableList<Any> {
        var listResult = mutableListOf<Any>()
        try {

            var strResult = decodeString(key).toString()
            listResult = String2List(strResult)
        } catch (e: Exception) {
            e.printStackTrace()
        }


        return listResult
    }

    fun String2List(string: String): MutableList<Any> {
        val mobileBytes: ByteArray = Base64.decode(
            string.toByteArray(),
            Base64.DEFAULT
        )
        val byteArrayInputStream = ByteArrayInputStream(
            mobileBytes
        )
        val objectInputStream = ObjectInputStream(
            byteArrayInputStream
        )
        val SceneList = objectInputStream.readObject() as MutableList<Any>
        objectInputStream.close()
        return SceneList
    }

    fun SceneList2String(mutableList: List<Any>): String {
        // 实例化一个ByteArrayOutputStream对象，用来装载压缩后的字节文件。

// 实例化一个ByteArrayOutputStream对象，用来装载压缩后的字节文件。
        val byteArrayOutputStream = ByteArrayOutputStream()
// 然后将得到的字符数据装载到ObjectOutputStream
        // 然后将得到的字符数据装载到ObjectOutputStream
        val objectOutputStream = ObjectOutputStream(
            byteArrayOutputStream
        )
// writeObject 方法负责写入特定类的对象的状态，以便相应的 readObject 方法可以还原它
        // writeObject 方法负责写入特定类的对象的状态，以便相应的 readObject 方法可以还原它
        objectOutputStream.writeObject(mutableList)
// 最后，用Base64.encode将字节文件转换成Base64编码保存在String中
        // 最后，用Base64.encode将字节文件转换成Base64编码保存在String中
        var SceneListString = String(
            Base64.encode(
                byteArrayOutputStream.toByteArray(), Base64.DEFAULT
            )
        )
// 关闭objectOutputStream
        // 关闭objectOutputStream
        objectOutputStream.close()
        return SceneListString
    }

}
